class FlowChart {
    constructor(container) {
        this.container = container;
        this.nodes = new Map();
        this.selectedNodes = new Set();
        this.minimap = document.getElementById('flowMinimap');
        this.minimapViewport = this.minimap.querySelector('.minimap-viewport');
        this.scale = 0.15; // 缩略图缩放比例
        this.isSelecting = false;
        this.selectionBox = null;
        this.startPos = { x: 0, y: 0 };
        this.isShiftKeyPressed = false; // 添加Shift键状态跟踪

        // 拖拽相关属性
        this.isDraggingCanvas = false;
        this.dragStartPos = { x: 0, y: 0 };
        this.dragStartScroll = { left: 0, top: 0 };

        // 交互模式：pointer(指针模式) 或 hand(手模式)
        this.interactionMode = 'pointer';

        // 连线模式状态
        this.isConnectionMode = false;
        this.sourceEndpoint = null;

        // 缩放相关属性
        this.zoomScale = 1;
        this.minZoom = 0.5;
        this.maxZoom = 2;
        this.zoomStep = 0.1;
        this.isZoomLocked = false;

        // 创建背景容器
        this.createBackgroundGrid();



        // 初始化jsPlumb实例
        this.jsPlumb = jsPlumb.getInstance({
            Container: container,
            Connector: ['Bezier', { curviness: 50 }],
            Endpoint: ['Dot', { radius: 5 }],
            PaintStyle: {
                stroke: '#6c757d',
                strokeWidth: 2
            },
            HoverPaintStyle: {
                stroke: '#007bff'
            },
            ConnectionOverlays: [
                ['Arrow', {
                    location: 1,
                    width: 10,
                    length: 10
                }]
            ],
            // 显式设置端点样式
            EndpointStyle: {
                fill: '#6c757d',
                stroke: '#6c757d',
                radius: 5,
                strokeWidth: 1
            },
            EndpointHoverStyle: {
                fill: '#007bff',
                stroke: '#007bff'
            },
            // 确保连接点可见
            EndpointHoverClass: 'endpoint-hover',
            // 添加拖拽相关配置
            DragOptions: {
                cursor: 'move',
                zIndex: 2000,
                grid: [10, 10]
            },
            // 设置节点可拖拽
            draggable: true
        });

        this.initializeJsPlumb();
        this.initializeMinimap();
        this.initializeMultiSelect();
        this.initializeZoomControls();
        this.initializeCanvasDrag();
        this.initializeModeControls();

        // 更新容器的交互模式CSS类
        this.updateContainerClass();

        // 监听窗口大小变化，确保画布始终填满容器
        window.addEventListener('resize', this.handleResize.bind(this));

        // 初始化时调整一次
        this.handleResize();
    }

    createBackgroundGrid() {
        // 创建固定大小的背景网格元素
        this.gridContainer = document.createElement('div');
        this.gridContainer.className = 'grid-container';
        this.gridContainer.style.position = 'absolute';
        this.gridContainer.style.top = '0';
        this.gridContainer.style.left = '0';
        this.gridContainer.style.width = '100%';
        this.gridContainer.style.height = '100%';
        this.gridContainer.style.minWidth = '5000px';
        this.gridContainer.style.minHeight = '5000px';
        this.gridContainer.style.pointerEvents = 'none';
        this.gridContainer.style.backgroundImage = 'radial-gradient(circle at 1px 1px, #e0e0e0 1px, transparent 1px)';
        this.gridContainer.style.backgroundSize = '20px 20px';
        this.gridContainer.style.zIndex = '-1';

        // 添加到容器的最前面
        this.container.insertBefore(this.gridContainer, this.container.firstChild);
    }

    initializeJsPlumb() {
        this.jsPlumb.setContainer(this.container);

        // 设置默认连接线样式
        this.jsPlumb.importDefaults({
            Connector: ['Bezier', { curviness: 50 }],
            Endpoint: ['Dot', { radius: 5 }],
            PaintStyle: {
                stroke: '#6c757d',
                strokeWidth: 2
            },
            HoverPaintStyle: {
                stroke: '#007bff'
            },
            ConnectionOverlays: [
                ['Arrow', {
                    location: 1,
                    width: 10,
                    length: 10
                }]
            ],
            EndpointStyle: {
                fill: '#6c757d',
                stroke: '#6c757d',
                radius: 5,
                strokeWidth: 1
            },
            EndpointHoverStyle: {
                fill: '#007bff',
                stroke: '#007bff'
            },
            DragOptions: {
                cursor: 'move',
                zIndex: 2000,
                grid: [10, 10],
                containment: true,
                stop: function (e) {
                    // 重新绘制所有连接
                    this.jsPlumb.repaintEverything();
                }.bind(this)
            }
        });

        // 设置连接建立时的事件处理
        this.jsPlumb.bind('connection', (info) => {
            console.log('Connection made:', info);

            // 为新创建的连接添加中间按钮和点击事件
            this.addConnectionAddButton(info.connection);

            // 连接完成后，隐藏所有左侧连接点
            this.hideAllLeftEndpoints();

            // 移除连线模式标记
            document.body.classList.remove('connecting');

            // 触发连接模式变化事件
            document.dispatchEvent(new CustomEvent('connectionModeChange', {
                detail: {
                    isConnecting: false,
                    sourceNodeId: null
                }
            }));
        });

        // 设置连接前的验证
        this.jsPlumb.bind('beforeDrop', (info) => {
            // 阻止连接到自身
            if (info.sourceId === info.targetId) {
                console.log('阻止连接到自身');
                return false;
            }
            return true;
        });

        // 设置连接断开时的事件处理
        this.jsPlumb.bind('connectionDetached', (info) => {
            console.log('Connection detached:', info);

            // 如果连接有关联的加号按钮，移除它
            if (info.connection.addButton && info.connection.addButton.parentNode) {
                info.connection.addButton.parentNode.removeChild(info.connection.addButton);
            }

            // 移除连线模式标记
            document.body.classList.remove('connecting');

            // 触发连接模式变化事件
            document.dispatchEvent(new CustomEvent('connectionModeChange', {
                detail: {
                    isConnecting: false,
                    sourceNodeId: null
                }
            }));
        });

        // 监听连接拖拽开始事件
        // 监听连接鼠标悬浮事件
        this.jsPlumb.bind('connectionMoved', (info) => {
            console.log('Connection moved:', info);

            // 如果原连接有关联的加号按钮，移除它
            if (info.originalSourceEndpoint && info.originalSourceEndpoint.connection &&
                info.originalSourceEndpoint.connection.addButton &&
                info.originalSourceEndpoint.connection.addButton.parentNode) {
                info.originalSourceEndpoint.connection.addButton.parentNode.removeChild(
                    info.originalSourceEndpoint.connection.addButton
                );
            }

            // 为新位置添加按钮
            if (info.connection) {
                this.addConnectionAddButton(info.connection);
            }
        });

        // 监听连接拖拽开始事件
        this.jsPlumb.bind('connectionDrag', (connection) => {
            console.log('连接拖拽开始', connection);
            // 获取源节点ID
            const sourceId = connection.sourceId;

            // 添加连线模式标记到body
            document.body.classList.add('connecting');
            // 显示所有节点的左侧连接点，但排除源节点
            this.showAllLeftEndpoints(sourceId);

            // 触发连接模式变化事件
            document.dispatchEvent(new CustomEvent('connectionModeChange', {
                detail: {
                    isConnecting: true,
                    sourceNodeId: sourceId
                }
            }));
        });

        // 监听连接拖拽停止事件
        this.jsPlumb.bind('connectionDragStop', () => {
            console.log('连接拖拽停止');
            // 延迟移除连线模式，确保连接建立后再移除
            setTimeout(() => {
                // 移除连线模式标记
                document.body.classList.remove('connecting');
                // 隐藏所有左侧连接点
                this.hideAllLeftEndpoints();

                // 触发连接模式变化事件
                document.dispatchEvent(new CustomEvent('connectionModeChange', {
                    detail: {
                        isConnecting: false,
                        sourceNodeId: null
                    }
                }));
            }, 200);
        });

        // 初始化导出JSON按钮
        this.initializeExportButton();
    }

    initializeMinimap() {
        // 监听画布滚动
        this.container.addEventListener('scroll', () => {
            this.updateMinimapViewport();
        });

        // 监听窗口大小变化
        window.addEventListener('resize', () => {
            this.updateMinimapViewport();
        });

        // 初始化缩略图视口
        this.updateMinimapViewport();

        // 添加缩略图拖拽功能
        let isDragging = false;
        let startX, startY;

        this.minimapViewport.addEventListener('mousedown', (e) => {
            isDragging = true;
            startX = e.clientX - this.minimapViewport.offsetLeft;
            startY = e.clientY - this.minimapViewport.offsetTop;
            this.minimapViewport.style.cursor = 'grabbing';
        });

        document.addEventListener('mousemove', (e) => {
            if (!isDragging) return;

            const x = e.clientX - startX;
            const y = e.clientY - startY;

            // 计算边界
            const maxX = this.minimap.clientWidth - this.minimapViewport.clientWidth;
            const maxY = this.minimap.clientHeight - this.minimapViewport.clientHeight;

            const boundedX = Math.max(0, Math.min(x, maxX));
            const boundedY = Math.max(0, Math.min(y, maxY));

            // 更新视口位置
            this.minimapViewport.style.left = `${boundedX}px`;
            this.minimapViewport.style.top = `${boundedY}px`;

            // 更新画布滚动位置
            this.container.scrollLeft = (boundedX / this.scale);
            this.container.scrollTop = (boundedY / this.scale);
        });

        document.addEventListener('mouseup', () => {
            isDragging = false;
            this.minimapViewport.style.cursor = 'grab';
        });
    }

    updateMinimapViewport() {
        // 如果minimap不存在，直接返回
        if (!this.minimap || !this.minimapViewport) return;

        // 获取容器和画布的尺寸信息
        const containerRect = this.container.getBoundingClientRect();
        const containerWidth = containerRect.width;
        const containerHeight = containerRect.height;

        // 获取完整内容尺寸（可滚动区域）
        const contentWidth = Math.max(this.container.scrollWidth, containerWidth);
        const contentHeight = Math.max(this.container.scrollHeight, containerHeight);

        // 确保小地图尺寸信息可用
        const minimapWidth = this.minimap.clientWidth;
        const minimapHeight = this.minimap.clientHeight;

        if (!minimapWidth || !minimapHeight) return;

        // 计算视口在小地图中的尺寸比例
        const viewportWidth = (containerWidth / contentWidth) * minimapWidth;
        const viewportHeight = (containerHeight / contentHeight) * minimapHeight;

        // 计算视口在小地图中的位置
        const scrollRatioX = this.container.scrollLeft / (contentWidth - containerWidth || 1);
        const scrollRatioY = this.container.scrollTop / (contentHeight - containerHeight || 1);

        const viewportX = scrollRatioX * (minimapWidth - viewportWidth);
        const viewportY = scrollRatioY * (minimapHeight - viewportHeight);

        // 更新视口样式
        Object.assign(this.minimapViewport.style, {
            width: `${Math.max(20, viewportWidth)}px`, // 确保至少有最小尺寸
            height: `${Math.max(20, viewportHeight)}px`,
            left: `${viewportX}px`,
            top: `${viewportY}px`,
            cursor: 'grab'
        });

        // 在视口更新后，确保节点位置也更新
        this.updateMinimapNodes();
    }

    initializeMultiSelect() {
        // 创建选择框
        this.selectionBox = document.createElement('div');
        this.selectionBox.className = 'selection-box';
        this.container.appendChild(this.selectionBox);

        // 监听画布鼠标事件
        this.container.addEventListener('mousedown', (e) => {
            // 如果点击的是节点或其子元素，不启动框选
            if (e.target.closest('.flow-node') || this.isDraggingCanvas) return;

            // 只有在指针模式下才允许框选
            if (this.interactionMode !== 'pointer') return;

            // 只有按下鼠标左键时才启动框选
            if (e.button !== 0) return;

            // 开始选择，并添加selecting类以改变鼠标样式
            this.isSelecting = true;
            this.container.classList.add('selecting');
            const rect = this.container.getBoundingClientRect();

            // 考虑缩放因素计算起始位置
            this.startPos = {
                x: (e.clientX - rect.left) / this.zoomScale + this.container.scrollLeft,
                y: (e.clientY - rect.top) / this.zoomScale + this.container.scrollTop
            };

            // 设置选择框的初始位置和大小
            this.selectionBox.style.left = `${this.startPos.x}px`;
            this.selectionBox.style.top = `${this.startPos.y}px`;
            this.selectionBox.style.width = '0px';
            this.selectionBox.style.height = '0px';
            this.selectionBox.style.display = 'block';

            // 如果没有按住Shift键，清除所有已选择的节点
            if (!e.shiftKey) {
                this.clearSelection();
            }
        });

        this.container.addEventListener('mousemove', (e) => {
            if (!this.isSelecting) return;

            const rect = this.container.getBoundingClientRect();

            // 考虑缩放因素计算当前位置
            const currentX = (e.clientX - rect.left) / this.zoomScale + this.container.scrollLeft;
            const currentY = (e.clientY - rect.top) / this.zoomScale + this.container.scrollTop;

            const width = Math.abs(currentX - this.startPos.x);
            const height = Math.abs(currentY - this.startPos.y);
            const left = Math.min(currentX, this.startPos.x);
            const top = Math.min(currentY, this.startPos.y);

            this.selectionBox.style.left = `${left}px`;
            this.selectionBox.style.top = `${top}px`;
            this.selectionBox.style.width = `${width}px`;
            this.selectionBox.style.height = `${height}px`;

            // 检查节点是否在选择框内，只在框选面积足够大时触发检查
            if (width > 5 && height > 5) {
                this.checkNodesInSelection(left, top, width, height);
            }
        });

        this.container.addEventListener('mouseup', () => {
            if (this.isSelecting) {
                this.isSelecting = false;
                this.selectionBox.style.display = 'none';
                this.container.classList.remove('selecting');
            }
        });

        // 监听键盘事件
        document.addEventListener('keydown', (e) => {
            if (e.key === 'Shift') {
                this.isShiftKeyPressed = true;
            }

            // Ctrl+A 或 Cmd+A 全选
            if ((e.ctrlKey || e.metaKey) && e.key === 'a') {
                e.preventDefault();
                this.selectAllNodes();
            }

            // Delete 或 Backspace 删除选中的节点
            if (e.key === 'Delete' || e.key === 'Backspace') {
                this.deleteSelectedNodes();
            }
        });

        document.addEventListener('keyup', (e) => {
            if (e.key === 'Shift') {
                this.isShiftKeyPressed = false;
            }
        });
    }

    checkNodesInSelection(left, top, width, height) {
        // 标记哪些节点在选择框内
        const nodesInSelection = new Set();

        this.nodes.forEach((node, nodeId) => {
            const element = document.getElementById(nodeId);
            if (!element) return;

            // 获取节点位置和尺寸，考虑缩放因素
            const nodeLeft = node.position.x;
            const nodeTop = node.position.y;
            const nodeWidth = element.offsetWidth / this.zoomScale;
            const nodeHeight = element.offsetHeight / this.zoomScale;

            // 判断节点是否与选择框相交
            const isIntersecting = (
                nodeLeft < left + width &&
                nodeLeft + nodeWidth > left &&
                nodeTop < top + height &&
                nodeTop + nodeHeight > top
            );

            if (isIntersecting) {
                // 添加到框选节点集合中
                nodesInSelection.add(nodeId);
                this.selectNode(nodeId);
            } else if (!this.isShiftKeyPressed && this.selectedNodes.has(nodeId) && !nodesInSelection.has(nodeId)) {
                // 如果不是按住Shift键，且节点已被选中但不在当前框选中，则取消选择
                this.deselectNode(nodeId);
            }
        });
    }

    selectNode(nodeId) {
        const element = document.getElementById(nodeId);


        if (element) {
            element.classList.add('selected');
            this.selectedNodes.add(nodeId);

            // 只显示右侧（输出）连接点
            const endpoints = this.jsPlumb.getEndpoints(nodeId);
            if (endpoints && endpoints.length > 0) {
                endpoints.forEach(endpoint => {
                    // 检查是否是右侧端点
                    const isRightEndpoint =
                        (endpoint.anchor && endpoint.anchor.type === "Right") ||
                        (endpoint.anchor && endpoint.anchor.orientation && endpoint.anchor.orientation[0] === 1) ||
                        (endpoint.cssClass && endpoint.cssClass.includes('right-endpoint')) ||
                        (endpoint.canvas && endpoint.canvas.getAttribute('data-anchor') === 'Right');

                    // 检查是否是左侧端点和是否处于连接模式
                    const isLeftEndpoint =
                        (endpoint.anchor && endpoint.anchor.type === "Left") ||
                        (endpoint.anchor && endpoint.anchor.orientation && endpoint.anchor.orientation[0] === -1) ||
                        (endpoint.cssClass && endpoint.cssClass.includes('left-endpoint')) ||
                        (endpoint.canvas && endpoint.canvas.getAttribute('data-anchor') === 'Left');

                    const isConnectingMode = document.body.classList.contains('connecting');

                    if (endpoint.canvas && isRightEndpoint) {
                        // 右侧端点始终可见
                        endpoint.canvas.classList.add('endpoint-visible');
                        endpoint.canvas.style.opacity = '1';
                        endpoint.canvas.style.visibility = 'visible';
                    } else if (endpoint.canvas && isLeftEndpoint && isConnectingMode) {
                        // 仅在连接模式下显示左侧端点
                        endpoint.canvas.classList.add('endpoint-visible');
                        endpoint.canvas.style.opacity = '1';
                        endpoint.canvas.style.visibility = 'visible';
                    }
                })

            }
        }

        this.updateMinimapNodes();
    }

    deselectNode(nodeId) {
        const element = document.getElementById(nodeId);
        if (element) {
            element.classList.remove('selected');
            this.selectedNodes.delete(nodeId);

            // 立即隐藏连接点，不考虑悬浮状态
            const endpoints = this.jsPlumb.getEndpoints(nodeId);
            if (endpoints && endpoints.length > 0) {
                endpoints.forEach(endpoint => {
                    if (endpoint.canvas) {
                        endpoint.canvas.classList.remove('endpoint-visible');
                        endpoint.canvas.style.opacity = '0';
                        endpoint.canvas.style.visibility = 'hidden';

                        // 确保没有悬浮或点击事件妨碍隐藏
                        endpoint.canvas.style.pointerEvents = 'none';

                        // 短暂延迟后恢复指针事件，以便后续操作
                        setTimeout(() => {
                            if (endpoint.canvas) {
                                endpoint.canvas.style.pointerEvents = '';
                            }
                        }, 100);
                    }
                });
            }

            this.updateMinimapNodes();
        }
    }

    clearSelection() {
        this.selectedNodes.forEach(nodeId => {
            const element = document.getElementById(nodeId);
            if (element) {
                element.classList.remove('selected');

                // 隐藏该节点的所有连接点
                const endpoints = this.jsPlumb.getEndpoints(nodeId);
                if (endpoints && endpoints.length > 0) {
                    endpoints.forEach(endpoint => {
                        if (endpoint.canvas) {
                            endpoint.canvas.classList.remove('endpoint-visible');
                            endpoint.canvas.style.opacity = '0';
                            endpoint.canvas.style.visibility = 'hidden';
                        }
                    });
                }
            }
        });
        this.selectedNodes.clear();
        this.updateMinimapNodes();
    }

    selectAllNodes() {
        this.nodes.forEach((node, nodeId) => {
            this.selectNode(nodeId);
        });
    }

    deleteSelectedNodes() {
        this.selectedNodes.forEach(nodeId => {
            this.removeNode(nodeId);
        });
        this.selectedNodes.clear();
        this.updateMinimapNodes();
    }

    updateMinimapNodes() {
        // 清除现有的缩略图节点
        const existingNodes = this.minimap.querySelectorAll('.minimap-node');
        existingNodes.forEach(node => node.remove());

        // 获取容器和画布的尺寸信息
        const containerWidth = this.container.scrollWidth;
        const containerHeight = this.container.scrollHeight;
        const minimapWidth = this.minimap.clientWidth;
        const minimapHeight = this.minimap.clientHeight;

        // 为每个节点创建缩略图表示
        this.nodes.forEach((node, nodeId) => {
            const element = document.getElementById(nodeId);
            if (!element) return;

            // 计算节点在小地图中的位置和大小
            const minimapNode = document.createElement('div');
            minimapNode.className = `minimap-node ${node.type}-node`;

            // 添加选中状态
            if (this.selectedNodes.has(nodeId)) {
                minimapNode.classList.add('selected');
            }

            // 计算小地图中节点的位置和大小，考虑缩放
            const nodeLeft = (node.position.x / containerWidth) * minimapWidth;
            const nodeTop = (node.position.y / containerHeight) * minimapHeight;
            const nodeWidth = Math.max(5, (element.offsetWidth / this.zoomScale / containerWidth) * minimapWidth);
            const nodeHeight = Math.max(5, (element.offsetHeight / this.zoomScale / containerHeight) * minimapHeight);

            // 设置节点样式
            Object.assign(minimapNode.style, {
                left: `${nodeLeft}px`,
                top: `${nodeTop}px`,
                width: `${nodeWidth}px`,
                height: `${nodeHeight}px`,
                backgroundColor: this.getNodeColor(node.type),
                border: this.selectedNodes.has(nodeId) ? '2px solid #fff' : '1px solid rgba(0,0,0,0.1)'
            });

            this.minimap.appendChild(minimapNode);
        });
    }

    addNode(node) {
        const element = node.createDOMElement();
        this.container.appendChild(element);
        this.nodes.set(node.id, node);

        // 添加节点点击事件
        element.addEventListener('click', (e) => {
            e.stopPropagation();

            if (e.shiftKey) {
                // Shift+点击切换选择状态
                if (this.selectedNodes.has(node.id)) {
                    this.deselectNode(node.id);
                } else {
                    this.selectNode(node.id);
                }
            } else {
                // 修改点击逻辑，避免连接点闪烁问题
                // 只有当前节点未被选中时才清除其他选择
                if (!this.selectedNodes.has(node.id)) {
                    this.clearSelection();
                    this.selectNode(node.id);
                }
            }
        });

        // 添加鼠标悬浮事件处理
        element.addEventListener('mouseenter', () => {
            // 确保只显示右侧连接点，除非在连接模式下
            const endpoints = this.jsPlumb.getEndpoints(node.id);
            if (endpoints && endpoints.length > 0) {
                endpoints.forEach(endpoint => {
                    // 检查是否是右侧端点
                    const isRightEndpoint = endpoint.anchor &&
                        (endpoint.anchor.type === "Right" ||
                            (endpoint.anchor.orientation && endpoint.anchor.orientation[0] === 1));

                    // 检查是否是左侧端点和是否处于连接模式
                    const isLeftEndpoint = endpoint.anchor &&
                        (endpoint.anchor.type === "Left" ||
                            (endpoint.anchor.orientation && endpoint.anchor.orientation[0] === -1));

                    const isConnectingMode = document.body.classList.contains('connecting');

                    if (endpoint.canvas && isRightEndpoint) {
                        // 右侧端点始终可见
                        endpoint.canvas.classList.add('endpoint-visible');
                        endpoint.canvas.style.opacity = '1';
                        endpoint.canvas.style.visibility = 'visible';
                    } else if (endpoint.canvas && isLeftEndpoint && isConnectingMode) {
                        // 仅在连接模式下显示左侧端点
                        endpoint.canvas.classList.add('endpoint-visible');
                        endpoint.canvas.style.opacity = '1';
                        endpoint.canvas.style.visibility = 'visible';
                    }
                });
            }
        });

        element.addEventListener('mouseleave', () => {
            // 如果节点未被选中，则隐藏连接点
            if (!this.selectedNodes.has(node.id)) {
                const endpoints = this.jsPlumb.getEndpoints(node.id);
                if (endpoints && endpoints.length > 0) {
                    endpoints.forEach(endpoint => {
                        if (endpoint.canvas) {
                            endpoint.canvas.classList.remove('endpoint-visible');
                            endpoint.canvas.style.opacity = '0';
                            endpoint.canvas.style.visibility = 'hidden';
                        }
                    });
                }
            }
        });

        // 使节点可拖拽
        this.jsPlumb.draggable(element, {
            grid: [10, 10],
            containment: true,
            start: (e) => {
                // 添加拖拽状态类
                element.classList.add('dragging');

                // 记录开始拖动时所有选中节点的初始位置
                if (this.selectedNodes.has(node.id)) {
                    this.selectedNodes.forEach(selectedId => {
                        const selectedElement = document.getElementById(selectedId);
                        if (selectedElement) {
                            selectedElement.classList.add('dragging');
                            selectedElement._startPos = {
                                left: parseInt(selectedElement.style.left, 10) || 0,
                                top: parseInt(selectedElement.style.top, 10) || 0
                            };
                        }
                    });
                } else {
                    element._startPos = {
                        left: parseInt(element.style.left, 10) || 0,
                        top: parseInt(element.style.top, 10) || 0
                    };
                }

                // 暂时禁用连接点
                this.jsPlumb.setDraggable(element, false);
            },
            drag: (e) => {
                // 计算拖动的偏移量
                const dx = parseInt(element.style.left, 10) - element._startPos.left;
                const dy = parseInt(element.style.top, 10) - element._startPos.top;

                // 如果当前节点被选中，同时移动其他选中的节点
                if (this.selectedNodes.has(node.id)) {
                    this.selectedNodes.forEach(selectedId => {
                        if (selectedId !== node.id) {
                            const selectedElement = document.getElementById(selectedId);
                            if (selectedElement && selectedElement._startPos) {
                                selectedElement.style.left = `${selectedElement._startPos.left + dx}px`;
                                selectedElement.style.top = `${selectedElement._startPos.top + dy}px`;
                                // 重新绘制连接线
                                this.jsPlumb.revalidate(selectedElement);
                            }
                        }
                    });
                }

                // 更新当前节点位置数据
                node.position.x = parseInt(element.style.left, 10);
                node.position.y = parseInt(element.style.top, 10);

                // 更新小地图
                this.updateMinimapNodes();
            },
            stop: (e) => {
                // 移除拖拽状态类
                element.classList.remove('dragging');

                // 更新所有选中节点的位置数据
                if (this.selectedNodes.has(node.id)) {
                    this.selectedNodes.forEach(selectedId => {
                        const selectedElement = document.getElementById(selectedId);
                        if (selectedElement) {
                            selectedElement.classList.remove('dragging');
                            const selectedNode = this.nodes.get(selectedId);
                            if (selectedNode) {
                                selectedNode.position.x = parseInt(selectedElement.style.left, 10);
                                selectedNode.position.y = parseInt(selectedElement.style.top, 10);
                            }
                        }
                    });
                }

                // 重新启用连接点
                this.jsPlumb.setDraggable(element, true);

                // 更新小地图
                this.updateMinimapNodes();
                this.updateMinimapViewport();
            }
        });

        // 添加端点
        this.addEndpoints(element, node.type);

        // 更新小地图
        this.updateMinimapNodes();

        return element;
    }

    addEndpoints(element, type) {
        const commonOptions = {
            maxConnections: -1,
            connector: ['Bezier', { curviness: 50 }],
            endpoint: ['Dot', { radius: 8 }], // 增大端点半径
            paintStyle: {
                fill: '#6c757d',
                stroke: '#6c757d',
                strokeWidth: 2
            },
            hoverPaintStyle: {
                fill: '#007bff',
                stroke: '#007bff',
                strokeWidth: 2,
                scale: 1.2
            },
            connectorPaintStyle: {
                strokeWidth: 2,
                stroke: '#6c757d'
            },
            connectorHoverStyle: {
                strokeWidth: 3,
                stroke: '#007bff'
            },
            // 添加class和data属性，辅助CSS选择器匹配
            cssClass: 'node-endpoint'
        };

        // 为端点添加点击事件的通用处理函数
        const addEndpointClickHandler = (endpoint, anchor) => {
            if (!endpoint || !endpoint.canvas) return; // 确保端点存在

            // 设置数据属性，帮助CSS选择器匹配
            if (endpoint.canvas) {
                endpoint.canvas.setAttribute('data-nodeid', element.id);
                endpoint.canvas.setAttribute('data-anchor', anchor);
                endpoint.canvas.setAttribute('data-type', type);
            }

            endpoint.canvas.addEventListener('click', (e) => {
                e.stopPropagation(); // 阻止事件冒泡
                // 确保端点可见（有时点击时DOM元素还存在但视觉上不可见）
                endpoint.canvas.classList.add('endpoint-visible');
                this.createEndpointMenu(endpoint, element.id, type, anchor);
            });
        };

        // 开始节点只有输出端点
        if (type === 'start') {
            const endpoint = this.jsPlumb.addEndpoint(element, {
                anchor: 'Right',
                isSource: true,
                isTarget: false,
                ...commonOptions,
                cssClass: 'node-endpoint right-endpoint',
                attributes: {
                    'data-anchor': 'Right',
                    'data-type': type
                }
            });
            addEndpointClickHandler(endpoint, 'Right');
        }
        // 结束节点只有输入端点
        else if (type === 'end') {
            const endpoint = this.jsPlumb.addEndpoint(element, {
                anchor: 'Left',
                isSource: false,
                isTarget: true,
                ...commonOptions,
                cssClass: 'node-endpoint left-endpoint',
                attributes: {
                    'data-anchor': 'Left',
                    'data-type': type
                }
            });
            addEndpointClickHandler(endpoint, 'Left');
        }
        // 条件判断节点有一个输入和两个输出(true/false)
        else if (type === 'ifelse') {
            // 输入端点 - 左侧中间
            const inputEndpoint = this.jsPlumb.addEndpoint(element, {
                anchor: 'Left',
                isSource: false,
                isTarget: true,
                ...commonOptions,
                cssClass: 'node-endpoint left-endpoint',
                attributes: {
                    'data-anchor': 'Left',
                    'data-type': type
                }
            });
            addEndpointClickHandler(inputEndpoint, 'Left');

            // True输出端点 - 右上 (更靠上一些)
            const truthyEndpoint = this.jsPlumb.addEndpoint(element, {
                anchor: [1, 0.25, 1, 0], // 右侧, 距顶部25%
                isSource: true,
                isTarget: false,
                ...commonOptions,
                cssClass: 'node-endpoint right-top-endpoint',
                attributes: {
                    'data-anchor': 'RightTop',
                    'data-type': type
                },
                overlays: [
                    ['Label', {
                        label: 'True',
                        location: [0.5, -1.5], // 在端点上方显示
                        cssClass: 'endpoint-label endpoint-label-true',
                        id: 'true-label'
                    }]
                ]
            });
            addEndpointClickHandler(truthyEndpoint, 'RightTop');

            // False输出端点 - 右下 (更靠下一些)
            const falsyEndpoint = this.jsPlumb.addEndpoint(element, {
                anchor: [1, 0.75, 1, 0], // 右侧, 距顶部75%
                isSource: true,
                isTarget: false,
                ...commonOptions,
                cssClass: 'node-endpoint right-bottom-endpoint',
                attributes: {
                    'data-anchor': 'RightBottom',
                    'data-type': type
                },
                overlays: [
                    ['Label', {
                        label: 'False',
                        location: [0.5, 2.5], // 进一步向下调整位置
                        cssClass: 'endpoint-label endpoint-label-false',
                        id: 'false-label'
                    }]
                ]
            });
            addEndpointClickHandler(falsyEndpoint, 'RightBottom');
        }
        // 迭代器节点有一个输入，一个循环输出和一个完成输出
        else if (type === 'iterator') {
            // 输入端点 - 左侧中间
            const inputEndpoint = this.jsPlumb.addEndpoint(element, {
                anchor: 'Left',
                isSource: false,
                isTarget: true,
                ...commonOptions,
                cssClass: 'node-endpoint left-endpoint',
                attributes: {
                    'data-anchor': 'Left',
                    'data-type': type
                }
            });
            addEndpointClickHandler(inputEndpoint, 'Left');

            // 循环输出端点 - 右上 (更靠上一些)
            const loopEndpoint = this.jsPlumb.addEndpoint(element, {
                anchor: [1, 0.25, 1, 0], // 右侧, 距顶部25%
                isSource: true,
                isTarget: false,
                ...commonOptions,
                cssClass: 'node-endpoint right-top-endpoint',
                attributes: {
                    'data-anchor': 'RightTop',
                    'data-type': type
                },
                overlays: [
                    ['Label', {
                        label: '循环',
                        location: [0.5, -1.5], // 在端点上方显示
                        cssClass: 'endpoint-label endpoint-label-loop',
                        id: 'loop-label'
                    }]
                ]
            });
            addEndpointClickHandler(loopEndpoint, 'RightTop');

            // 完成输出端点 - 右下 (更靠下一些)
            const completeEndpoint = this.jsPlumb.addEndpoint(element, {
                anchor: [1, 0.75, 1, 0], // 右侧, 距顶部75%
                isSource: true,
                isTarget: false,
                ...commonOptions,
                cssClass: 'node-endpoint right-bottom-endpoint',
                attributes: {
                    'data-anchor': 'RightBottom',
                    'data-type': type
                },
                overlays: [
                    ['Label', {
                        label: '完成',
                        location: [0.5, 2.5], // 进一步向下调整位置
                        cssClass: 'endpoint-label endpoint-label-complete',
                        id: 'complete-label'
                    }]
                ]
            });
            addEndpointClickHandler(completeEndpoint, 'RightBottom');
        }
        // 其他节点都有标准的输入和输出端点
        else {
            const inputEndpoint = this.jsPlumb.addEndpoint(element, {
                anchor: 'Left',
                isSource: false,
                isTarget: true,
                ...commonOptions,
                cssClass: 'node-endpoint left-endpoint',
                attributes: {
                    'data-anchor': 'Left',
                    'data-type': type
                }
            });
            addEndpointClickHandler(inputEndpoint, 'Left');

            const outputEndpoint = this.jsPlumb.addEndpoint(element, {
                anchor: 'Right',
                isSource: true,
                isTarget: false,
                ...commonOptions,
                cssClass: 'node-endpoint right-endpoint',
                attributes: {
                    'data-anchor': 'Right',
                    'data-type': type
                }
            });
            addEndpointClickHandler(outputEndpoint, 'Right');
        }

        // 添加样式表，确保标签显示在最上层
        const style = document.createElement('style');
        style.textContent = `
            .endpoint-label {
                z-index: 1000 !important;
                font-weight: bold;
                pointer-events: none;
                background-color: white !important;
                padding: 2px 6px !important;
                border-radius: 4px !important;
                border: 1px solid #ddd !important;
                box-shadow: 0 1px 3px rgba(0,0,0,0.1) !important;
            }
            
            /* 特定端点标签样式 */
            .endpoint-label-true, .endpoint-label-loop {
                color: #28a745 !important;
            }
            
            .endpoint-label-false, .endpoint-label-complete {
                color: #dc3545 !important;
            }
        `;
        document.head.appendChild(style);

        // 为每个右侧连接点添加鼠标事件监听器
        const rightEndpoints = element.querySelectorAll('.jtk-endpoint[data-anchor*="Right"], .right-endpoint, .branch-endpoint');
        rightEndpoints.forEach(endpoint => {
            endpoint.addEventListener('mouseenter', () => {
                // 当鼠标进入连接点时，显示所有右侧连接点
                rightEndpoints.forEach(ep => {
                    ep.style.opacity = '1';
                    ep.style.visibility = 'visible';
                    ep.style.zIndex = '200';
                });
            });

            endpoint.addEventListener('mouseleave', () => {
                // 当鼠标离开连接点时，检查节点是否仍在悬浮状态
                const node = endpoint.closest('.flow-node');
                if (!node.matches(':hover')) {
                    rightEndpoints.forEach(ep => {
                        ep.style.opacity = '0';
                        ep.style.visibility = 'hidden';
                    });
                }
            });
        });

        // 为节点添加鼠标事件监听器
        element.addEventListener('mouseenter', () => {
            rightEndpoints.forEach(ep => {
                ep.style.opacity = '1';
                ep.style.visibility = 'visible';
                ep.style.zIndex = '200';
            });
        });

        element.addEventListener('mouseleave', () => {
            rightEndpoints.forEach(ep => {
                ep.style.opacity = '0';
                ep.style.visibility = 'hidden';
            });
        });
    }

    removeNode(nodeId) {
        const node = this.nodes.get(nodeId);
        if (node) {
            const element = document.getElementById(nodeId);
            this.jsPlumb.remove(element);
            this.nodes.delete(nodeId);

            // 更新小地图
            this.updateMinimapNodes();
            this.updateMinimapViewport();
        }
    }

    updateNode(nodeId, updates) {
        const node = this.nodes.get(nodeId);
        if (node) {
            Object.assign(node, updates);
            const element = document.getElementById(nodeId);
            const newElement = node.createDOMElement();
            element.parentNode.replaceChild(newElement, element);

            // 重新添加拖拽和连接点
            this.jsPlumb.draggable(newElement, {
                grid: [10, 10],
                containment: true,
                drag: () => {
                    // 更新节点位置数据
                    node.position.x = parseInt(newElement.style.left, 10);
                    node.position.y = parseInt(newElement.style.top, 10);

                    // 拖动时更新小地图
                    this.updateMinimapNodes();
                },
                stop: () => {
                    // 拖动结束后更新小地图
                    this.updateMinimapNodes();
                    this.updateMinimapViewport();
                }
            });
            this.addEndpoints(newElement, node.type);

            // 更新小地图
            this.updateMinimapNodes();
        }
    }

    getNodeData(nodeId) {
        return this.nodes.get(nodeId);
    }

    toJSON() {
        const nodesData = Array.from(this.nodes.values()).map(node => node.toJSON());
        const connections = this.jsPlumb.getConnections().map(conn => ({
            source: conn.source.id,
            target: conn.target.id
        }));

        return {
            nodes: nodesData,
            connections: connections
        };
    }

    loadFromJSON(data) {
        // 清除现有的节点和连接
        this.jsPlumb.reset();
        this.nodes.clear();

        // 保留背景网格和选择框，清除其他内容
        const gridContainer = this.gridContainer;
        const selectionBox = this.selectionBox;

        // 移除所有子元素
        while (this.container.firstChild) {
            this.container.removeChild(this.container.firstChild);
        }

        // 重新添加必要的元素
        this.container.appendChild(gridContainer);
        this.container.appendChild(selectionBox);

        // 重新创建节点
        data.nodes.forEach(nodeData => {
            const node = new FlowNode(nodeData.type, nodeData.id, nodeData.position);
            node.updateName(nodeData.name);
            node.updateParams(nodeData.params);
            if (nodeData.prompt) {
                node.updatePrompt(nodeData.prompt);
            }
            this.addNode(node);
        });

        // 重新创建连接
        data.connections.forEach(conn => {
            this.jsPlumb.connect({
                source: conn.source,
                target: conn.target
            });
        });
    }

    initializeZoomControls() {
        // 获取控制按钮
        const zoomInBtn = document.querySelector('.zoom-in');
        const zoomOutBtn = document.querySelector('.zoom-out');
        const zoomFitBtn = document.querySelector('.zoom-fit');
        const zoomLockBtn = document.querySelector('.zoom-lock');
        const centerNodesBtn = document.querySelector('.center-nodes');

        // 点击放大按钮
        if (zoomInBtn) {
            zoomInBtn.addEventListener('click', () => {
                if (!this.isZoomLocked) {
                    this.zoomIn();
                }
            });
        }

        // 点击缩小按钮
        if (zoomOutBtn) {
            zoomOutBtn.addEventListener('click', () => {
                if (!this.isZoomLocked) {
                    this.zoomOut();
                }
            });
        }

        // 点击适应画布按钮
        if (zoomFitBtn) {
            zoomFitBtn.addEventListener('click', () => {
                if (!this.isZoomLocked) {
                    this.zoomToFit();
                }
            });
        }

        // 点击整理画布按钮
        if (centerNodesBtn) {
            centerNodesBtn.addEventListener('click', () => {
                if (!this.isZoomLocked) {
                    this.centerNodes();
                }
            });
        }

        // 点击锁定按钮
        if (zoomLockBtn) {
            zoomLockBtn.addEventListener('click', () => {
                this.toggleZoomLock();
                zoomLockBtn.classList.toggle('active');
                if (this.isZoomLocked) {
                    zoomLockBtn.querySelector('i').className = 'fas fa-lock';
                    this.container.classList.add('locked');
                } else {
                    zoomLockBtn.querySelector('i').className = 'fas fa-lock-open';
                    this.container.classList.remove('locked');
                }
            });
        }

        // 添加鼠标滚轮缩放事件
        this.container.addEventListener('wheel', (e) => {
            if (this.isZoomLocked) return;

            e.preventDefault();

            // 计算鼠标位置相对于画布的坐标
            const rect = this.container.getBoundingClientRect();
            const offsetX = e.clientX - rect.left;
            const offsetY = e.clientY - rect.top;

            // 根据滚轮方向决定缩放方向
            if (e.deltaY < 0) {
                this.zoomAtPoint(this.zoomScale + this.zoomStep, offsetX, offsetY);
            } else {
                this.zoomAtPoint(this.zoomScale - this.zoomStep, offsetX, offsetY);
            }
        });
    }

    zoomIn() {
        const newScale = Math.min(this.zoomScale + this.zoomStep, this.maxZoom);
        this.zoom(newScale);
    }

    zoomOut() {
        const newScale = Math.max(this.zoomScale - this.zoomStep, this.minZoom);
        this.zoom(newScale);
    }

    zoom(scale) {
        this.zoomScale = scale;
        this.applyZoom();
    }

    zoomAtPoint(scale, x, y) {
        // 限制缩放范围
        const newScale = Math.max(this.minZoom, Math.min(this.maxZoom, scale));

        // 如果缩放比例没有变化，不执行缩放
        if (newScale === this.zoomScale) return;

        // 记录当前滚动位置
        const scrollLeft = this.container.scrollLeft;
        const scrollTop = this.container.scrollTop;

        // 计算鼠标在内容中的相对位置
        const mouseXInContent = scrollLeft + x / this.zoomScale;
        const mouseYInContent = scrollTop + y / this.zoomScale;

        // 应用新的缩放比例
        const oldScale = this.zoomScale;
        this.zoomScale = newScale;
        this.applyZoom();

        // 计算新的滚动位置，使鼠标位置对应的内容点保持不变
        const newScrollLeft = mouseXInContent - x / newScale;
        const newScrollTop = mouseYInContent - y / newScale;

        // 设置新的滚动位置
        this.container.scrollLeft = newScrollLeft;
        this.container.scrollTop = newScrollTop;
    }

    zoomToFit() {
        // 如果没有节点，恢复到默认缩放
        if (this.nodes.size === 0) {
            this.zoom(1);
            return;
        }

        // 计算所有节点的边界
        let minX = Infinity, minY = Infinity;
        let maxX = -Infinity, maxY = -Infinity;

        this.nodes.forEach((node) => {
            const element = document.getElementById(node.id);
            if (element) {
                const left = node.position.x;
                const top = node.position.y;
                const right = left + element.offsetWidth;
                const bottom = top + element.offsetHeight;

                minX = Math.min(minX, left);
                minY = Math.min(minY, top);
                maxX = Math.max(maxX, right);
                maxY = Math.max(maxY, bottom);
            }
        });

        // 添加边距
        const padding = 50;
        minX -= padding;
        minY -= padding;
        maxX += padding;
        maxY += padding;

        // 计算合适的缩放比例
        const width = maxX - minX;
        const height = maxY - minY;
        const containerWidth = this.container.clientWidth;
        const containerHeight = this.container.clientHeight;

        const scaleX = containerWidth / width;
        const scaleY = containerHeight / height;

        // 取较小的缩放比例，确保所有内容都可见
        const scale = Math.min(scaleX, scaleY, this.maxZoom);
        const finalScale = Math.max(scale, this.minZoom);

        // 应用缩放
        this.zoom(finalScale);

        // 调整滚动位置，使内容居中
        this.container.scrollLeft = minX * this.zoomScale + (width * this.zoomScale - containerWidth) / 2;
        this.container.scrollTop = minY * this.zoomScale + (height * this.zoomScale - containerHeight) / 2;
    }

    applyZoom() {
        // 单独处理网格容器的缩放，保持网格大小一致
        const gridSize = 20;  // 固定网格大小
        this.gridContainer.style.backgroundSize = `${gridSize}px ${gridSize}px`;

        // 应用缩放样式
        this.container.style.transform = `scale(${this.zoomScale})`;
        this.container.style.transformOrigin = '0 0';

        // 调整容器尺寸以确保即使在缩放时仍然占满父容器
        const invScale = 1 / this.zoomScale;
        this.container.style.width = `${100 * invScale}%`;
        this.container.style.height = `${100 * invScale}%`;

        // 添加缩放状态类
        this.container.classList.toggle('zoomed', this.zoomScale !== 1);

        // 更新jsPlumb连线
        this.jsPlumb.setZoom(this.zoomScale);

        // 更新缩略图
        this.updateMinimapViewport();
        this.updateMinimapNodes();
    }

    toggleZoomLock() {
        this.isZoomLocked = !this.isZoomLocked;
    }

    // 整理画布，居中显示所有节点
    centerNodes() {
        // 如果没有节点，不需要处理
        if (this.nodes.size === 0) {
            return;
        }

        // 计算所有节点的边界
        let minX = Infinity, minY = Infinity;
        let maxX = -Infinity, maxY = -Infinity;

        this.nodes.forEach((node) => {
            const element = document.getElementById(node.id);
            if (element) {
                const left = node.position.x;
                const top = node.position.y;
                const right = left + element.offsetWidth / this.zoomScale;
                const bottom = top + element.offsetHeight / this.zoomScale;

                minX = Math.min(minX, left);
                minY = Math.min(minY, top);
                maxX = Math.max(maxX, right);
                maxY = Math.max(maxY, bottom);
            }
        });

        // 计算节点区域的中心
        const centerX = (minX + maxX) / 2;
        const centerY = (minY + maxY) / 2;

        // 计算画布的中心
        const containerWidth = this.container.clientWidth / this.zoomScale;
        const containerHeight = this.container.clientHeight / this.zoomScale;
        const containerCenterX = containerWidth / 2;
        const containerCenterY = containerHeight / 2;

        // 计算需要移动的距离
        const deltaX = containerCenterX - centerX;
        const deltaY = containerCenterY - centerY;

        // 移动所有节点
        this.nodes.forEach((node, nodeId) => {
            const element = document.getElementById(nodeId);
            if (element) {
                // 更新节点位置
                node.position.x += deltaX;
                node.position.y += deltaY;

                // 更新DOM元素位置
                element.style.left = `${node.position.x}px`;
                element.style.top = `${node.position.y}px`;

                // 重新绘制连接线
                this.jsPlumb.revalidate(element);
            }
        });

        // 更新缩略图
        this.updateMinimapNodes();
    }

    // 添加窗口大小变化处理函数
    handleResize() {
        // 获取父容器尺寸
        const parentContainer = this.container.parentElement;
        if (!parentContainer) return;

        // 确保网格容器足够大
        const viewportWidth = parentContainer.clientWidth;
        const viewportHeight = parentContainer.clientHeight;

        // 根据当前视口和缩放级别计算所需的最小画布尺寸
        const minWidth = Math.max(5000, viewportWidth * 3);
        const minHeight = Math.max(5000, viewportHeight * 3);

        // 根据实际需要调整网格容器尺寸
        this.gridContainer.style.minWidth = `${minWidth}px`;
        this.gridContainer.style.minHeight = `${minHeight}px`;

        // 重新应用缩放以确保画布占满容器
        this.applyZoom();
    }

    // 创建左下角拖拽图标
    createDragIcon() {
        const dragIcon = document.createElement('div');
        dragIcon.className = 'drag-icon';
        dragIcon.innerHTML = '<i class="fas fa-arrows-alt"></i>';
        dragIcon.title = '在空白区域拖拽可移动画布';

        // 添加到canvas-container的父元素
        const canvasContainer = this.container.parentElement;
        if (canvasContainer) {
            canvasContainer.appendChild(dragIcon);
        }
    }

    // 初始化画布拖拽
    initializeCanvasDrag() {
        // 监听鼠标按下事件
        this.container.addEventListener('mousedown', (e) => {
            // 如果点击的是节点或其子元素，不启动画布拖拽
            if (e.target.closest('.flow-node') || e.button !== 0) return;

            // 在手模式下，允许拖动画布；在指针模式下，只有按住空格键才允许拖动
            if (this.interactionMode !== 'hand' && !e.code === 'Space') return;

            // 阻止指针模式下的框选
            if (this.interactionMode === 'hand' && this.isSelecting) {
                this.isSelecting = false;
                this.selectionBox.style.display = 'none';
                this.container.classList.remove('selecting');
            }

            // 记录鼠标按下位置
            this.dragStartPos = {
                x: e.clientX,
                y: e.clientY
            };

            // 记录当前滚动位置
            this.dragStartScroll = {
                left: this.container.scrollLeft,
                top: this.container.scrollTop
            };

            // 设置拖动状态
            if (this.interactionMode === 'hand') {
                this.isDraggingCanvas = true;
                this.container.style.cursor = 'grabbing';
            } else {
                // 在指针模式下，需要达到一定移动距离才设置为拖动状态
                const mouseMoveHandler = (moveEvent) => {
                    // 计算移动距离
                    const dx = moveEvent.clientX - this.dragStartPos.x;
                    const dy = moveEvent.clientY - this.dragStartPos.y;
                    const distance = Math.sqrt(dx * dx + dy * dy);

                    // 如果移动距离超过阈值，且不是正在框选，启动画布拖拽
                    if (distance > 5 && !this.isSelecting) {
                        this.isDraggingCanvas = true;
                        this.container.style.cursor = 'grabbing';

                        // 移除临时监听器
                        document.removeEventListener('mousemove', mouseMoveHandler);
                    }
                };

                const mouseUpHandler = () => {
                    document.removeEventListener('mousemove', mouseMoveHandler);
                    document.removeEventListener('mouseup', mouseUpHandler);
                };

                document.addEventListener('mousemove', mouseMoveHandler);
                document.addEventListener('mouseup', mouseUpHandler);
            }
        });

        // 监听鼠标移动事件
        document.addEventListener('mousemove', (e) => {
            if (!this.isDraggingCanvas) return;

            // 计算鼠标移动距离
            const dx = e.clientX - this.dragStartPos.x;
            const dy = e.clientY - this.dragStartPos.y;

            // 设置滚动位置
            this.container.scrollLeft = this.dragStartScroll.left - dx;
            this.container.scrollTop = this.dragStartScroll.top - dy;

            // 更新缩略图视口
            this.updateMinimapViewport();
        });

        // 监听鼠标抬起事件
        document.addEventListener('mouseup', () => {
            if (!this.isDraggingCanvas) return;

            // 重置画布拖拽状态
            this.isDraggingCanvas = false;

            // 恢复鼠标样式
            this.container.style.cursor = '';
        });
    }

    // 添加交互模式控制功能
    initializeModeControls() {
        // 获取交互模式按钮
        const pointerBtn = document.querySelector('.pointer');
        const handBtn = document.querySelector('.hand');

        // 更新按钮激活状态
        const updateButtonState = () => {
            pointerBtn.classList.toggle('active', this.interactionMode === 'pointer');
            handBtn.classList.toggle('active', this.interactionMode === 'hand');
        };

        // 点击切换交互模式
        pointerBtn.addEventListener('click', () => {
            this.interactionMode = 'pointer';
            this.updateContainerClass();
            updateButtonState();
        });

        handBtn.addEventListener('click', () => {
            this.interactionMode = 'hand';
            this.updateContainerClass();
            updateButtonState();
        });

        // 初始化按钮状态
        updateButtonState();
    }

    // 更新容器的交互模式CSS类
    updateContainerClass() {
        this.container.classList.remove('pointer', 'hand');
        this.container.classList.add(this.interactionMode);
    }

    // 获取节点颜色
    getNodeColor(type) {
        // 为不同类型的节点设置不同颜色
        const colorMap = {
            'start': '#4CAF50', // 绿色
            'end': '#F44336',   // 红色
            'model': '#2196F3', // 蓝色
            'agent': '#9C27B0', // 紫色
            'ifelse': '#FF9800', // 橙色
            'iterator': '#795548', // 棕色
            'code': '#607D8B',  // 蓝灰色
            'template': '#00BCD4', // 青色
            'http': '#FFEB3B',  // 黄色
            'database': '#009688', // 青绿色
            'email': '#E91E63'  // 粉红色
        };

        return colorMap[type] || '#9E9E9E'; // 默认灰色
    }

    // 为连接点添加点击菜单
    createEndpointMenu(endpoint, nodeId, nodeType, anchor) {
        const menu = document.createElement('div');
        menu.className = 'connection-menu endpoint-menu';

        // 获取端点位置
        const rect = endpoint.canvas.getBoundingClientRect();

        // 设置菜单样式
        Object.assign(menu.style, {
            position: 'absolute',
            left: `${rect.left + rect.width / 2}px`,
            top: `${rect.top + rect.height / 2}px`,
            backgroundColor: '#fff',
            boxShadow: '0 2px 10px rgba(0,0,0,0.2)',
            borderRadius: '4px',
            padding: '8px 0',
            zIndex: '1000',
            minWidth: '160px',
            transform: 'translate(-50%, 20px)'
        });

        // 根据节点类型和锚点位置生成不同的菜单选项
        let menuItems = [];

        if (anchor.includes('Right')) {
            // 输出端点菜单
            menuItems = [
                { label: '添加连接到...', icon: 'fa-link', action: 'connect' },
                { label: '添加后续节点', icon: 'fa-plus-circle', action: 'add-node' }
            ];
        } else {
            // 输入端点菜单
            menuItems = [
                { label: '删除连接', icon: 'fa-unlink', action: 'disconnect' }
            ];
        }

        // 创建菜单项
        menuItems.forEach(item => {
            const menuItem = document.createElement('div');
            menuItem.className = 'menu-item';
            menuItem.innerHTML = `<i class="fas ${item.icon}"></i> ${item.label}`;

            Object.assign(menuItem.style, {
                padding: '8px 16px',
                cursor: 'pointer',
                whiteSpace: 'nowrap',
                display: 'flex',
                alignItems: 'center',
                gap: '8px'
            });

            menuItem.addEventListener('mouseover', () => {
                menuItem.style.backgroundColor = '#f0f4f8';
            });

            menuItem.addEventListener('mouseout', () => {
                menuItem.style.backgroundColor = '';
            });

            menuItem.addEventListener('click', () => {
                // 处理菜单项点击事件
                this.handleEndpointMenuAction(item.action, nodeId, endpoint);
                // 关闭菜单
                document.body.removeChild(menu);
            });

            menu.appendChild(menuItem);
        });

        // 添加关闭菜单的事件
        document.addEventListener('click', function closeMenu(e) {
            if (!menu.contains(e.target) && !endpoint.canvas.contains(e.target)) {
                if (document.body.contains(menu)) {
                    document.body.removeChild(menu);
                }
                document.removeEventListener('click', closeMenu);
            }
        });

        document.body.appendChild(menu);
        return menu;
    }

    // 为连接线添加中间加号按钮
    addConnectionAddButton(connection) {
        // 创建加号按钮元素
        const addButton = document.createElement('div');
        addButton.className = 'connection-add-button';
        addButton.innerHTML = '<i class="fas fa-plus"></i>';

        // 添加到DOM
        document.body.appendChild(addButton);

        // 更新按钮位置
        const updatePosition = () => {
            // 获取连接线中点位置
            const connector = connection.connector;
            let midpoint = { x: 0, y: 0 };

            if (connector.getPath) {
                midpoint = connector.getPath().midpoint;
            } else {
                // 备用方法，如果getPath不可用
                const sourceXY = connection.endpoints[0].anchor.lastReturnValue;
                const targetXY = connection.endpoints[1].anchor.lastReturnValue;
                midpoint.x = (sourceXY[0] + targetXY[0]) / 2;
                midpoint.y = (sourceXY[1] + targetXY[1]) / 2;
            }

            // 获取画布位置和缩放
            const canvasRect = this.container.getBoundingClientRect();
            const scale = this.zoomScale;

            // 计算按钮在页面中的位置
            const left = midpoint.x * scale + canvasRect.left;
            const top = midpoint.y * scale + canvasRect.top;

            // 更新按钮位置
            addButton.style.left = `${left}px`;
            addButton.style.top = `${top}px`;
        };

        // 初始定位
        updatePosition();

        // 添加鼠标事件监听 - 修改为直接设置样式属性
        connection.bind('mouseenter', () => {
            addButton.style.opacity = '1';
            addButton.style.visibility = 'visible';
            updatePosition(); // 确保位置正确
        });

        connection.bind('mouseleave', () => {
            // 只有当鼠标不在按钮上时才隐藏按钮
            if (!addButton.matches(':hover')) {
                addButton.style.opacity = '0';
                addButton.style.visibility = 'hidden';
            }
        });

        // 为按钮添加鼠标事件
        addButton.addEventListener('mouseenter', () => {
            addButton.style.opacity = '1';
            addButton.style.visibility = 'visible';
            addButton.style.transform = 'translate(-50%, -50%) scale(1.2)';
            addButton.style.backgroundColor = '#f8f9fa';
            addButton.style.borderColor = '#007bff';
            addButton.style.color = '#007bff';
        });

        addButton.addEventListener('mouseleave', () => {
            addButton.style.transform = 'translate(-50%, -50%) scale(1)';
            addButton.style.backgroundColor = '#fff';
            addButton.style.borderColor = '#6c757d';
            addButton.style.color = '#6c757d';

            // 检查连接线是否仍处于hover状态
            if (!connection.isHover()) {
                addButton.style.opacity = '0';
                addButton.style.visibility = 'hidden';
            }
        });

        // 按钮点击显示菜单
        addButton.addEventListener('click', (e) => {
            e.stopPropagation(); // 阻止事件冒泡
            this.createConnectionMenu(connection);
        });

        // 存储按钮引用以便稍后清理
        connection.addButton = addButton;

        // 在连接被移除时清理按钮
        connection.bind('removed', () => {
            if (addButton && addButton.parentNode) {
                addButton.parentNode.removeChild(addButton);
            }
        });

        // 当画布缩放或滚动时更新位置
        this.container.addEventListener('scroll', updatePosition);
        connection.bind('cssChange', updatePosition);
    }

    // 为连接线添加中间加号按钮和点击显示菜单
    createConnectionMenu(connection) {
        const menu = document.createElement('div');
        menu.className = 'connection-menu';

        // 获取连接线中点位置
        const connector = connection.connector;
        const midpoint = connector.getPath ?
            connector.getPath().midpoint :
            { x: (connector.x1 + connector.x2) / 2, y: (connector.y1 + connector.y2) / 2 };

        // 转换为页面坐标
        const canvasRect = this.container.getBoundingClientRect();
        const x = midpoint.x * this.zoomScale + canvasRect.left;
        const y = midpoint.y * this.zoomScale + canvasRect.top;

        // 设置菜单样式
        Object.assign(menu.style, {
            position: 'fixed', // 改为fixed定位，避免滚动影响
            left: `${x}px`,
            top: `${y}px`,
            backgroundColor: '#fff',
            boxShadow: '0 2px 10px rgba(0,0,0,0.2)',
            borderRadius: '4px',
            padding: '8px 0',
            zIndex: '1000',
            minWidth: '160px',
            transform: 'translate(-50%, -50%)' // 确保居中显示
        });

        // 定义菜单项
        const menuItems = [
            { label: '添加中间节点', icon: 'fa-plus-circle', action: 'add-middle-node' },
            { label: '移除连接', icon: 'fa-trash', action: 'remove-connection' }
        ];

        // 创建菜单项
        menuItems.forEach(item => {
            const menuItem = document.createElement('div');
            menuItem.className = 'menu-item';
            menuItem.innerHTML = `<i class="fas ${item.icon}"></i> ${item.label}`;

            menuItem.addEventListener('mouseover', () => {
                menuItem.style.backgroundColor = '#f0f4f8';
            });

            menuItem.addEventListener('mouseout', () => {
                menuItem.style.backgroundColor = '';
            });

            menuItem.addEventListener('click', (e) => {
                e.stopPropagation(); // 阻止事件冒泡
                // 处理菜单项点击事件
                this.handleConnectionMenuAction(item.action, connection);
                // 关闭菜单
                document.body.removeChild(menu);
            });

            menu.appendChild(menuItem);
        });

        // 将菜单添加到页面
        document.body.appendChild(menu);

        // 添加关闭菜单的事件
        document.addEventListener('click', function closeMenu(e) {
            if (!menu.contains(e.target)) {
                if (document.body.contains(menu)) {
                    document.body.removeChild(menu);
                }
                document.removeEventListener('click', closeMenu);
            }
        });
    }

    // 处理连接点菜单动作
    handleEndpointMenuAction(action, nodeId, endpoint) {
        const node = this.nodes.get(nodeId);

        switch (action) {
            case 'connect':
                // 进入连接模式，等待用户选择目标节点
                console.log('开始连接模式，请选择目标节点');
                // 这里可以添加连接模式的实现逻辑
                break;

            case 'add-node':
                // 添加新节点并连接
                // 获取当前节点的位置
                const sourceElement = document.getElementById(nodeId);
                const rect = sourceElement.getBoundingClientRect();
                const position = {
                    x: node.position.x + rect.width + 50,
                    y: node.position.y
                };

                // 弹出节点选择对话框
                this.showNodeSelectionDialog(position, nodeId, endpoint);
                break;

            case 'disconnect':
                // 断开所有连接到此端点的连接
                const connections = this.jsPlumb.getConnections({ target: endpoint.elementId });
                connections.forEach(conn => {
                    this.jsPlumb.deleteConnection(conn);
                });
                break;
        }
    }

    // 处理连接线菜单动作
    handleConnectionMenuAction(action, connection) {
        switch (action) {
            case 'add-middle-node':
                // 计算连接线中点位置
                const sourceElement = document.getElementById(connection.sourceId);
                const targetElement = document.getElementById(connection.targetId);
                const sourceNode = this.nodes.get(connection.sourceId);
                const targetNode = this.nodes.get(connection.targetId);

                // 计算中点位置
                const midX = (sourceNode.position.x + targetNode.position.x) / 2;
                const midY = (sourceNode.position.y + targetNode.position.y) / 2;

                const position = { x: midX, y: midY };

                // 显示节点选择对话框
                this.showNodeSelectionDialog(position, connection.sourceId, null, connection);
                break;

            case 'remove-connection':
                // 删除连接线
                this.jsPlumb.deleteConnection(connection);
                break;
        }
    }

    // 显示节点选择对话框
    showNodeSelectionDialog(position, sourceNodeId, sourceEndpoint, existingConnection = null) {
        // 创建对话框
        const dialog = document.createElement('div');
        dialog.className = 'node-selection-dialog';

        // 设置对话框样式
        Object.assign(dialog.style, {
            position: 'fixed',
            left: '50%',
            top: '50%',
            transform: 'translate(-50%, -50%)',
            backgroundColor: '#fff',
            boxShadow: '0 4px 20px rgba(0,0,0,0.15)',
            borderRadius: '8px',
            padding: '20px',
            zIndex: '2000',
            minWidth: '300px',
            maxWidth: '500px'
        });

        // 添加标题
        const title = document.createElement('h3');
        title.textContent = '选择节点类型';
        title.style.marginBottom = '16px';
        dialog.appendChild(title);

        // 创建节点类型列表
        const nodeTypes = [
            { type: 'model', name: '大模型节点', icon: 'fa-brain' },
            { type: 'agent', name: '智能体节点', icon: 'fa-robot' },
            { type: 'ifelse', name: '条件判断节点', icon: 'fa-code-branch' },
            { type: 'iterator', name: '迭代器节点', icon: 'fa-redo' },
            { type: 'code', name: '代码节点', icon: 'fa-code' },
            { type: 'template', name: '模板转换节点', icon: 'fa-file-alt' },
            { type: 'http', name: 'HTTP节点', icon: 'fa-globe' },
            { type: 'database', name: '数据库节点', icon: 'fa-database' },
            { type: 'email', name: '邮件节点', icon: 'fa-envelope' }
        ];

        // 创建节点类型选择列表
        const list = document.createElement('div');
        list.className = 'node-type-list';
        list.style.display = 'grid';
        list.style.gridTemplateColumns = 'repeat(2, 1fr)';
        list.style.gap = '12px';
        list.style.maxHeight = '300px';
        list.style.overflowY = 'auto';

        nodeTypes.forEach(nodeType => {
            const item = document.createElement('div');
            item.className = 'node-type-item';
            item.innerHTML = `
            <div style="display: flex; align-items: center; padding: 10px; border: 1px solid #e9ecef; border-radius: 6px; cursor: pointer;">
                <div style="width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; border-radius: 6px; margin-right: 12px; color: white; background-color: ${this.getNodeTypeColor(nodeType.type)}">
                    <i class="fas ${nodeType.icon}"></i>
                </div>
                <div>
                    <div style="font-weight: 500;">${nodeType.name}</div>
                </div>
            </div>
        `;

            item.addEventListener('mouseover', () => {
                item.querySelector('div').style.backgroundColor = '#f8f9fa';
            });

            item.addEventListener('mouseout', () => {
                item.querySelector('div').style.backgroundColor = '';
            });

            item.addEventListener('click', () => {
                // 创建新节点
                this.createNodeAndConnect(nodeType.type, position, sourceNodeId, sourceEndpoint, existingConnection);
                // 关闭对话框
                document.body.removeChild(dialog);
            });

            list.appendChild(item);
        });

        dialog.appendChild(list);

        // 添加取消按钮
        const cancelBtn = document.createElement('button');
        cancelBtn.textContent = '取消';
        cancelBtn.style.marginTop = '16px';
        cancelBtn.style.padding = '8px 16px';
        cancelBtn.style.borderRadius = '4px';
        cancelBtn.style.backgroundColor = '#f8f9fa';
        cancelBtn.style.border = '1px solid #ced4da';
        cancelBtn.style.cursor = 'pointer';
        cancelBtn.style.float = 'right';

        cancelBtn.addEventListener('click', () => {
            document.body.removeChild(dialog);
        });

        dialog.appendChild(cancelBtn);

        // 添加对话框到页面
        document.body.appendChild(dialog);
    }

    // 获取节点类型的颜色
    getNodeTypeColor(type) {
        const colorMap = {
            'model': '#4caf50',
            'agent': '#3f51b5',
            'ifelse': '#ff9800',
            'iterator': '#9c27b0',
            'code': '#009688',
            'template': '#8bc34a',
            'http': '#03a9f4',
            'database': '#673ab7',
            'email': '#e91e63'
        };

        return colorMap[type] || '#6c757d';
    }

    // 创建新节点并连接
    createNodeAndConnect(nodeType, position, sourceNodeId, sourceEndpoint, existingConnection = null) {
        // 创建新节点
        const newNode = NodeFactory.createNode(nodeType, position);
        const newElement = this.addNode(newNode);

        // 等待DOM更新和端点创建完成
        setTimeout(() => {
            // 如果是添加中间节点（在已有连接中间）
            if (existingConnection) {
                // 删除原有连接
                this.jsPlumb.deleteConnection(existingConnection);

                // 获取新节点的所有端点
                const allEndpoints = this.jsPlumb.getEndpoints(newNode.id);
                console.log('新节点所有端点:', allEndpoints);

                // 找到输入和输出端点
                let inputEndpoint = null;
                let outputEndpoint = null;

                allEndpoints.forEach(ep => {
                    // 检查端点的CSS类或位置标识输入/输出
                    if (ep.cssClass && ep.cssClass.includes('left-endpoint')) {
                        inputEndpoint = ep;
                    } else if (ep.cssClass && ep.cssClass.includes('right-endpoint')) {
                        outputEndpoint = ep;
                    }
                });

                // 创建源节点到新节点的连接
                if (inputEndpoint) {
                    this.jsPlumb.connect({
                        source: existingConnection.sourceId,
                        target: inputEndpoint
                    });
                }

                // 创建新节点到目标节点的连接
                if (outputEndpoint) {
                    this.jsPlumb.connect({
                        source: outputEndpoint,
                        target: existingConnection.targetId
                    });
                }
            }
            // 如果是添加后续节点
            else if (sourceNodeId && sourceEndpoint) {
                // 获取新节点的所有端点
                const allEndpoints = this.jsPlumb.getEndpoints(newNode.id);
                console.log('后续节点端点:', allEndpoints);

                // 找到输入端点
                let inputEndpoint = null;

                allEndpoints.forEach(ep => {
                    // 检查端点的CSS类或位置标识输入
                    if (ep.cssClass && ep.cssClass.includes('left-endpoint')) {
                        inputEndpoint = ep;
                    }
                });

                if (inputEndpoint) {
                    // 创建连接，明确指定目标端点为左侧输入端点
                    this.jsPlumb.connect({
                        source: sourceEndpoint,
                        target: inputEndpoint
                    });
                } else {
                    console.warn('无法找到新节点的输入端点');

                    // 退化方案：尝试直接连接到元素，但指定锚点
                    this.jsPlumb.connect({
                        source: sourceEndpoint,
                        target: newElement,
                        anchors: ["Right", "Left"]
                    });
                }
            }
        }, 100); // 延迟确保DOM和端点都已创建
    }

    hideAllLeftEndpoints() {
        // 如果处于连接模式，不隐藏左侧连接点
        if (document.body.classList.contains('connecting')) {
            return;
        }

        // 遍历所有节点
        this.nodes.forEach((node, nodeId) => {
            // 获取该节点的所有端点
            const endpoints = this.jsPlumb.getEndpoints(nodeId);
            if (!endpoints) return;

            // 隐藏所有左侧连接点
            endpoints.forEach(endpoint => {
                // 检查是否是左侧连接点
                const isLeftEndpoint =
                    (endpoint.anchor && endpoint.anchor.type === "Left") ||
                    (endpoint.anchor && endpoint.anchor.orientation && endpoint.anchor.orientation[0] === -1) ||
                    (endpoint.cssClass && endpoint.cssClass.includes('left-endpoint')) ||
                    (endpoint.canvas && endpoint.canvas.getAttribute('data-anchor') === 'Left');

                if (endpoint.canvas && isLeftEndpoint) {
                    // 隐藏左侧连接点
                    endpoint.canvas.classList.remove('endpoint-visible');
                    endpoint.canvas.style.opacity = '0';
                    endpoint.canvas.style.visibility = 'hidden';
                }
            });
        });
    }

    showAllLeftEndpoints(excludeNodeId = null) {
        // 遍历所有节点
        this.nodes.forEach((node, nodeId) => {
            // 如果是要排除的节点，则跳过
            if (excludeNodeId && nodeId.toString() === excludeNodeId.toString()) return;

            // 获取该节点的所有端点
            const endpoints = this.jsPlumb.getEndpoints(nodeId);
            if (!endpoints) return;

            // 显示所有左侧连接点
            endpoints.forEach(endpoint => {
                // 检查是否是左侧连接点
                const isLeftEndpoint =
                    (endpoint.anchor && endpoint.anchor.type === "Left") ||
                    (endpoint.anchor && endpoint.anchor.orientation && endpoint.anchor.orientation[0] === -1) ||
                    (endpoint.cssClass && endpoint.cssClass.includes('left-endpoint')) ||
                    (endpoint.canvas && endpoint.canvas.getAttribute('data-anchor') === 'Left');

                if (endpoint.canvas && isLeftEndpoint) {
                    // 显示左侧连接点
                    endpoint.canvas.classList.add('endpoint-visible');
                    endpoint.canvas.style.opacity = '1';
                    endpoint.canvas.style.visibility = 'visible';
                    endpoint.canvas.style.display = 'block'; // 确保显示
                }
            });
        });

        // 确保源节点的左侧连接点始终不可见
        if (excludeNodeId) {
            const sourceEndpoints = this.jsPlumb.getEndpoints(excludeNodeId);
            if (sourceEndpoints) {
                sourceEndpoints.forEach(endpoint => {
                    const isLeftEndpoint =
                        (endpoint.anchor && endpoint.anchor.type === "Left") ||
                        (endpoint.anchor && endpoint.anchor.orientation && endpoint.anchor.orientation[0] === -1) ||
                        (endpoint.cssClass && endpoint.cssClass.includes('left-endpoint')) ||
                        (endpoint.canvas && endpoint.canvas.getAttribute('data-anchor') === 'Left');

                    if (endpoint.canvas && isLeftEndpoint) {
                        endpoint.canvas.classList.remove('endpoint-visible');
                        endpoint.canvas.style.opacity = '0';
                        endpoint.canvas.style.visibility = 'hidden';
                        endpoint.canvas.style.display = 'none';
                    }
                });
            }
        }
    }

    // 添加导出JSON按钮初始化方法
    initializeExportButton() {
        // 查找或创建工具栏
        let toolbar = document.querySelector('.flow-toolbar');
        if (!toolbar) {
            toolbar = document.createElement('div');
            toolbar.className = 'flow-toolbar';
            // 添加工具栏样式
            const toolbarStyle = document.createElement('style');
            toolbarStyle.textContent = `
                .flow-toolbar {
                    position: fixed;
                    top: 20px;
                    right: 20px;
                    z-index: 1000;
                    display: flex;
                    gap: 10px;
                    padding: 10px;
                    background: white;
                    border-radius: 8px;
                    box-shadow: 0 2px 10px rgba(0,0,0,0.1);
                }
                .toolbar-btn {
                    display: flex;
                    align-items: center;
                    gap: 8px;
                    padding: 8px 16px;
                    color: white;
                    border: none;
                    border-radius: 4px;
                    cursor: pointer;
                    font-size: 14px;
                    font-weight: 500;
                    transition: all 0.3s ease;
                }
                .export-json {
                    background-color: #4CAF50;
                }
                .export-json:hover {
                    background-color: #45a049;
                }
                .import-json {
                    background-color: #2196F3;
                }
                .import-json:hover {
                    background-color: #1e88e5;
                }
                .toolbar-btn i {
                    font-size: 16px;
                }
                .json-modal, .json-export-modal {
                    position: fixed;
                    top: 0;
                    left: 0;
                    width: 100%;
                    height: 100%;
                    background-color: rgba(0,0,0,0.5);
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    z-index: 9999;
                }
                .modal-content {
                    background-color: white;
                    border-radius: 8px;
                    width: 80%;
                    max-width: 800px;
                    max-height: 80vh;
                    display: flex;
                    flex-direction: column;
                    box-shadow: 0 4px 20px rgba(0,0,0,0.2);
                }
                .modal-header {
                    padding: 15px 20px;
                    border-bottom: 1px solid #eee;
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                }
                .modal-header h3 {
                    margin: 0;
                    color: #333;
                }
                .close-btn {
                    background: none;
                    border: none;
                    font-size: 24px;
                    cursor: pointer;
                    color: #666;
                    padding: 0;
                    line-height: 1;
                }
                .close-btn:hover {
                    color: #333;
                }
                .modal-body {
                    padding: 20px;
                    overflow: auto;
                    flex-grow: 1;
                }
                .modal-body textarea {
                    width: 100%;
                    height: 300px;
                    border: 1px solid #ddd;
                    border-radius: 4px;
                    padding: 10px;
                    font-family: monospace;
                    resize: none;
                    line-height: 1.5;
                    font-size: 14px;
                }
                .modal-footer {
                    padding: 15px 20px;
                    border-top: 1px solid #eee;
                    display: flex;
                    justify-content: flex-end;
                    gap: 10px;
                }
                .modal-footer button {
                    padding: 8px 16px;
                    border-radius: 4px;
                    cursor: pointer;
                    border: none;
                    font-weight: 500;
                    transition: all 0.3s ease;
                    color: white;
                }
                .copy-btn, .import-btn {
                    background-color: #4CAF50;
                }
                .copy-btn:hover, .import-btn:hover {
                    background-color: #45a049;
                }
                .download-btn {
                    background-color: #2196F3;
                }
                .download-btn:hover {
                    background-color: #1e88e5;
                }
                .error-message {
                    color: #dc3545;
                    margin-top: 10px;
                    font-size: 14px;
                }
            `;
            document.head.appendChild(toolbarStyle);
            document.body.appendChild(toolbar);
        }

        // 创建导出按钮
        const exportBtn = document.createElement('button');
        exportBtn.className = 'toolbar-btn export-json';
        exportBtn.innerHTML = '<i class="fas fa-file-export"></i> 导出流程图';
        exportBtn.title = '导出流程图JSON数据';
        toolbar.appendChild(exportBtn);

        // 创建导入按钮
        const importBtn = document.createElement('button');
        importBtn.className = 'toolbar-btn import-json';
        importBtn.innerHTML = '<i class="fas fa-file-import"></i> 导入流程图';
        importBtn.title = '导入流程图JSON数据';
        toolbar.appendChild(importBtn);

        // 添加点击事件
        exportBtn.addEventListener('click', () => {
            this.exportFlowChartJson();
        });

        importBtn.addEventListener('click', () => {
            this.importFlowChartJson();
        });
    }

    // 导出流程图JSON数据
    exportFlowChartJson() {
        // 获取JSON数据
        const jsonData = this.toJSON();
        const jsonString = JSON.stringify(jsonData, null, 2);

        // 创建模态框显示JSON数据
        const modal = document.createElement('div');
        modal.className = 'json-export-modal';
        modal.innerHTML = `
            <div class="modal-content">
                <div class="modal-header">
                    <h3>流程图JSON数据</h3>
                    <button class="close-btn">&times;</button>
                </div>
                <div class="modal-body">
                    <textarea readonly>${jsonString}</textarea>
                </div>
                <div class="modal-footer">
                    <button class="copy-btn">复制到剪贴板</button>
                    <button class="download-btn">下载JSON文件</button>
                </div>
            </div>
        `;

        // 添加到DOM
        document.body.appendChild(modal);

        // 关闭按钮事件
        const closeBtn = modal.querySelector('.close-btn');
        closeBtn.addEventListener('click', () => {
            document.body.removeChild(modal);
        });

        // 点击模态框背景关闭
        modal.addEventListener('click', (e) => {
            if (e.target === modal) {
                document.body.removeChild(modal);
            }
        });

        // 复制按钮事件
        const copyBtn = modal.querySelector('.copy-btn');
        copyBtn.addEventListener('click', () => {
            const textarea = modal.querySelector('textarea');
            textarea.select();
            document.execCommand('copy');

            // 显示复制成功提示
            copyBtn.textContent = '已复制！';
            setTimeout(() => {
                copyBtn.textContent = '复制到剪贴板';
            }, 2000);
        });

        // 下载按钮事件
        const downloadBtn = modal.querySelector('.download-btn');
        downloadBtn.addEventListener('click', () => {
            const dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(jsonString);
            const downloadAnchorNode = document.createElement('a');
            downloadAnchorNode.setAttribute("href", dataStr);
            downloadAnchorNode.setAttribute("download", "flowchart_" + new Date().toISOString().slice(0, 10) + ".json");
            document.body.appendChild(downloadAnchorNode);
            downloadAnchorNode.click();
            downloadAnchorNode.remove();
        });
    }

    // 导入流程图JSON数据
    importFlowChartJson() {
        // 创建模态框
        const modal = document.createElement('div');
        modal.className = 'json-modal';
        modal.innerHTML = `
            <div class="modal-content">
                <div class="modal-header">
                    <h3>导入流程图JSON数据</h3>
                    <button class="close-btn">&times;</button>
                </div>
                <div class="modal-body">
                    <textarea placeholder="请粘贴JSON数据..."></textarea>
                    <div class="error-message"></div>
                </div>
                <div class="modal-footer">
                    <button class="import-btn">导入</button>
                </div>
            </div>
        `;

        // 添加到DOM
        document.body.appendChild(modal);

        // 关闭按钮事件
        const closeBtn = modal.querySelector('.close-btn');
        closeBtn.addEventListener('click', () => {
            document.body.removeChild(modal);
        });

        // 点击模态框背景关闭
        modal.addEventListener('click', (e) => {
            if (e.target === modal) {
                document.body.removeChild(modal);
            }
        });

        // 导入按钮事件
        const importBtn = modal.querySelector('.import-btn');
        const textarea = modal.querySelector('textarea');
        const errorMessage = modal.querySelector('.error-message');

        importBtn.addEventListener('click', () => {
            try {
                const jsonData = JSON.parse(textarea.value);

                // 验证JSON数据格式
                if (!jsonData.nodes || !Array.isArray(jsonData.nodes) || !jsonData.connections || !Array.isArray(jsonData.connections)) {
                    throw new Error('无效的JSON格式：缺少nodes或connections数组');
                }

                // 清除现有节点和连接
                this.jsPlumb.reset();
                this.nodes.clear();

                // 保留背景网格和选择框，清除其他内容
                const gridContainer = this.gridContainer;
                const selectionBox = this.selectionBox;

                // 移除所有子元素
                while (this.container.firstChild) {
                    this.container.removeChild(this.container.firstChild);
                }

                // 重新添加必要的元素
                this.container.appendChild(gridContainer);
                this.container.appendChild(selectionBox);

                // 重新创建节点
                jsonData.nodes.forEach(nodeData => {
                    const node = NodeFactory.createNode(nodeData.type, nodeData.position);
                    node.id = nodeData.id; // 保持原有ID
                    node.updateName(nodeData.name);
                    node.updateParams(nodeData.params);

                    // 根据节点类型处理特定属性
                    switch (nodeData.type) {
                        case 'model':
                            if (nodeData.prompt) node.updatePrompt(nodeData.prompt);
                            if (nodeData.modelType) node.modelType = nodeData.modelType;
                            if (nodeData.temperature) node.temperature = nodeData.temperature;
                            break;
                        case 'code':
                            if (nodeData.code) node.code = nodeData.code;
                            if (nodeData.language) node.language = nodeData.language;
                            break;
                        case 'ifelse':
                            if (nodeData.condition) node.condition = nodeData.condition;
                            break;
                        case 'iterator':
                            if (nodeData.iterationKey) node.iterationKey = nodeData.iterationKey;
                            if (nodeData.maxIterations) node.maxIterations = nodeData.maxIterations;
                            break;
                        case 'template':
                            if (nodeData.template) node.template = nodeData.template;
                            break;
                        case 'http':
                            if (nodeData.url) node.url = nodeData.url;
                            if (nodeData.method) node.method = nodeData.method;
                            if (nodeData.headers) node.headers = nodeData.headers;
                            if (nodeData.requestBody) node.requestBody = nodeData.requestBody;
                            break;
                        case 'database':
                            if (nodeData.connectionString) node.connectionString = nodeData.connectionString;
                            if (nodeData.query) node.query = nodeData.query;
                            break;
                        case 'agent':
                            if (nodeData.agentPrompt) node.agentPrompt = nodeData.agentPrompt;
                            if (nodeData.tools) node.tools = nodeData.tools;
                            break;
                        case 'email':
                            if (nodeData.to) node.to = nodeData.to;
                            if (nodeData.cc) node.cc = nodeData.cc;
                            if (nodeData.bcc) node.bcc = nodeData.bcc;
                            if (nodeData.subject) node.subject = nodeData.subject;
                            if (nodeData.body) node.body = nodeData.body;
                            if (nodeData.attachments) node.attachments = nodeData.attachments;
                            break;
                    }

                    this.addNode(node);
                });

                // 创建一个全局样式，确保在连接模式下左侧连接点可见
                const importStyle = document.createElement('style');
                importStyle.id = 'import-connection-style';
                importStyle.textContent = `
                    body.connecting .node-endpoint.left-endpoint {
                        opacity: 1 !important;
                        visibility: visible !important;
                        display: block !important;
                        z-index: 1000 !important;
                    }
                `;
                document.head.appendChild(importStyle);

                // 重新创建连接
                setTimeout(() => {
                    jsonData.connections.forEach(conn => {
                        // 阻止连接到自身
                        if (conn.source === conn.target) {
                            console.log('阻止连接到自身:', conn);
                            return;
                        }

                        // 获取源节点和目标节点的所有端点
                        const sourceEndpoints = this.jsPlumb.getEndpoints(conn.source);
                        const targetEndpoints = this.jsPlumb.getEndpoints(conn.target);

                        // 找到合适的端点
                        let sourceEndpoint = null;
                        let targetEndpoint = null;

                        // 查找源节点的输出端点
                        sourceEndpoints.forEach(ep => {
                            if (ep.isSource && !ep.isTarget) {
                                sourceEndpoint = ep;
                            }
                        });

                        // 查找目标节点的输入端点
                        targetEndpoints.forEach(ep => {
                            if (!ep.isSource && ep.isTarget) {
                                targetEndpoint = ep;
                            }
                        });

                        // 如果找到了合适的端点，创建连接
                        if (sourceEndpoint && targetEndpoint) {
                            this.jsPlumb.connect({
                                source: sourceEndpoint,
                                target: targetEndpoint
                            });
                        } else {
                            // 如果找不到合适的端点，使用默认连接方式
                            this.jsPlumb.connect({
                                source: conn.source,
                                target: conn.target,
                                anchors: ["Right", "Left"]
                            });
                        }
                    });

                    // 为所有节点添加自定义连接模式响应
                    document.addEventListener('connectionModeChange', (e) => {
                        const isConnecting = e.detail.isConnecting;
                        const sourceNodeId = e.detail.sourceNodeId; // 获取源节点ID

                        this.nodes.forEach((node, nodeId) => {
                            // 如果是源节点且正在连接中，则跳过 - 不显示源节点的左侧连接点
                            if (isConnecting && sourceNodeId && nodeId === sourceNodeId) return;

                            const endpoints = this.jsPlumb.getEndpoints(nodeId);
                            if (endpoints && endpoints.length > 0) {
                                endpoints.forEach(endpoint => {
                                    if (endpoint.canvas) {
                                        const isLeftEndpoint =
                                            (endpoint.anchor && endpoint.anchor.type === "Left") ||
                                            (endpoint.anchor && endpoint.anchor.orientation && endpoint.anchor.orientation[0] === -1) ||
                                            (endpoint.cssClass && endpoint.cssClass.includes('left-endpoint')) ||
                                            (endpoint.canvas && endpoint.canvas.getAttribute('data-anchor') === 'Left');

                                        if (isLeftEndpoint) {
                                            if (isConnecting) {
                                                endpoint.canvas.classList.add('endpoint-visible');
                                                endpoint.canvas.style.opacity = '1';
                                                endpoint.canvas.style.visibility = 'visible';
                                                endpoint.canvas.style.display = 'block';
                                            } else {
                                                if (!this.selectedNodes.has(nodeId)) {
                                                    endpoint.canvas.classList.remove('endpoint-visible');
                                                    endpoint.canvas.style.opacity = '0';
                                                    endpoint.canvas.style.visibility = 'hidden';
                                                }
                                            }
                                        }
                                    }
                                });
                            }
                        });
                    });

                    // 关闭模态框
                    document.body.removeChild(modal);

                    // 更新缩略图
                    this.updateMinimapNodes();
                    this.updateMinimapViewport();

                    // 自动调整视图以适应所有节点
                    this.zoomToFit();
                }, 100);
            } catch (error) {
                errorMessage.textContent = `导入失败：${error.message}`;
            }
        });
    }
} 